package com.hqbzl.c1.unsate;

import com.hqbzl.c1.cass.TestCas;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import sun.misc.Unsafe;

import java.lang.reflect.Field;

// 息己实现的 unsafe
@Slf4j
public class MyAccount {
    public static void main(String[] args) {
        final MyAccountCas account = new MyAccountCas(1000);
        TestCas.Account.demo(account);
    }

    static class MyAccountCas implements TestCas.Account {
        private int value;
        private static Unsafe unsafe;

        static {
            try {
                Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
                theUnsafe.setAccessible(true);
                unsafe = (Unsafe) theUnsafe.get(null);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        private int getValue() {
            return value;
        }

        private void compareAndWith(int num) {
            try {
                while (true) {
                    final int curr = this.value;
                    final int next = curr - num;
                    final long offset = unsafe.objectFieldOffset(this.getClass().getDeclaredField("value"));
                    if (unsafe.compareAndSwapInt(this, offset, curr, next)) {
                        break;
                    } else {
                        log.error("{}", Thread.currentThread().getName());
                    }
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }

        public MyAccountCas(int value) {
            this.value = value;
        }

        @Override
        public Integer getBalance() {
            return this.getValue();
        }

        @Override
        public void withdraw(Integer amount) {
            compareAndWith(amount);
        }
    }
}
